/**
 * @file midi_protocol.c
 * @brief MIDI协议查找表和辅助函数
 * @date 2025-11-04
 */

#include "midi_protocol.h"

/* 板号与MIDI音符范围映射表 -------------------------------------------------*/

/**
 * @brief 板号MIDI音符范围表
 * @note 按板号从大到小排列 (B11-B1), 对应琴键1-88
 */
typedef struct {
    uint8_t board_id;       /* 板号 (1-11, 对应B1-B11) */
    uint8_t note_start;     /* 起始MIDI音符 (十六进制) */
    uint8_t note_end;       /* 结束MIDI音符 (十六进制) */
    uint8_t key_start;      /* 起始琴键号 (1-88) */
    uint8_t key_end;        /* 结束琴键号 (1-88) */
} board_midi_range_t;

static const board_midi_range_t s_board_ranges[BOARD_COUNT] = {
    {11, 0x15, 0x1C, 1,  8},    /* B11: 琴键1-8 */
    {10, 0x1D, 0x24, 9,  16},   /* B10: 琴键9-16 */
    {9,  0x25, 0x2C, 17, 24},   /* B9:  琴键17-24 */
    {8,  0x2D, 0x34, 25, 32},   /* B8:  琴键25-32 */
    {7,  0x35, 0x3C, 33, 40},   /* B7:  琴键33-40 */
    {6,  0x3D, 0x44, 41, 48},   /* B6:  琴键41-48 */
    {5,  0x45, 0x4C, 49, 56},   /* B5:  琴键49-56 */
    {4,  0x4D, 0x54, 57, 64},   /* B4:  琴键57-64 */
    {3,  0x55, 0x5C, 65, 72},   /* B3:  琴键65-72 */
    {2,  0x5D, 0x64, 73, 80},   /* B2:  琴键73-80 */
    {1,  0x65, 0x6C, 81, 88}    /* B1:  琴键81-88 */
};

/* 辅助函数实现 -------------------------------------------------------------*/

/**
 * @brief 根据MIDI音符获取对应的板号
 * @param note MIDI音符号 (0x15-0x6C)
 * @return 板号 (1-11), 如果音符不在范围内返回0
 */
uint8_t midi_get_board_id(uint8_t note) {
    for (uint8_t i = 0; i < BOARD_COUNT; i++)
    {
        if (note >= s_board_ranges[i].note_start && note <= s_board_ranges[i].note_end)
        {
            return s_board_ranges[i].board_id;
        }
    }
    return 0; /* 不在任何板的范围内 */
}

/**
 * @brief 根据板号获取MIDI音符范围
 * @param board_id 板号 (1-11)
 * @param note_start 输出参数: 起始音符
 * @param note_end 输出参数: 结束音符
 * @return 0成功, -1失败(无效板号)
 */
int midi_get_note_range(uint8_t board_id, uint8_t *note_start, uint8_t *note_end) {
    if (board_id < BOARD_ID_MIN || board_id > BOARD_ID_MAX)
    {
        return -1;
    }

    for (uint8_t i = 0; i < BOARD_COUNT; i++)
    {
        if (s_board_ranges[i].board_id == board_id)
        {
            if (note_start) *note_start = s_board_ranges[i].note_start;
            if (note_end) *note_end = s_board_ranges[i].note_end;
            return 0;
        }
    }

    return -1;
}

/**
 * @brief 检查MIDI音符是否属于指定板号
 * @param note MIDI音符号
 * @param board_id 板号 (1-11)
 * @return true属于, false不属于
 */
bool midi_note_is_for_board(uint8_t note, uint8_t board_id) {
    return (midi_get_board_id(note) == board_id);
}

/******************************** 文件结束 *********************************/
